(function (line, support, document, global) {
    var dom = line.dom = line.dom || {};
    var siblingMap = {
        'firstChild':['firstElementChild', 'firstChild', 'nextSibling'],
        'lastChild':['lastElementChild', 'lastChild', 'previousSibling'],
        'previousSibling':['previousElementSibling', 'previousSibling', 'previousSibling'],
        'nextSibling':['nextElementSibling', 'nextSibling', 'nextSibling']
    };
    var sibling = (function () {
        if (support.firstElementChild) {
            return function (element, traversings) {
                return element[traversings[0]];
            };
        } else {
            return function (element, traversings) {
                var node = element[traversings[1]];
                if (dom.isElement(node)) {
                    return node;
                } else {
                    while (node && (node = node[traversings[2]])) {
                        if (node.nodeType == 1) {
                            return node;
                        }
                    }
                    return null;
                }
            };
        }
    }());


    line.extend(dom, {
        byId:function (id) {
            return document.getElementById(id);
        },
        isElement:function (element) {
            return element && element.nodeType === 1;
        },
        getDoc:function (element) {
            var doc = document;
            if (element) {
                doc = (element.nodeType === 9) ? element : // element === document
                    element.ownerDocument || // element === DOM node
                        element.document// element === window
            }
            return doc;
        },
        getWindow:function (element) {
            var doc = dom.getDoc(element);
            return doc.defaultView || doc.parentWindow || global;
        },
        firstChild:function (element) {
            return sibling(element, siblingMap['firstChild']);
        },
        lastChild:function (element) {
            return sibling(element, siblingMap['lastChild']);
        },
        previousSibling:function (element) {
            return sibling(element, siblingMap['previousSibling']);
        },
        nextSibling:function (element) {
            return sibling(element, siblingMap['nextSibling']);
        },
        children:(function () {
            if (support.firstElementChild) {
                return function (element) {
                    return element.children;
                };
            } else {
                return function (element) {
                    var result = [],
                        node = element.firstChild;
                    do {
                        if (dom.isElement(node)) {
                            result.push(node);
                        }
                    } while (node = node.nextSibling);
                    return result;
                }
            }
        }()),
        childAt:function (target, index) {
            var node = dom.firstChild(target),
                i = 0;
            for (; i < index; i++) {
                node = dom.nextSibling(node);
            }
            return node;
        },
        parent:function (element) {
            var node = element.parentElement || element.parentNode;
            return (node && node.nodeType != 11) ? node : null;
        },
        clone:function (element, deep) {
            return element.cloneNode(deep);
        },
        insert:function (target, element, index) {
            target.insertBefore(element, dom.childAt[index]);
            return target;
        },
        append:function (target, element) {
            target.appendChild(element);
            return target;
        },
        prepend:function (target, element) {
            var firstChild = target.firstChild;
            if (firstChild) {
                target.insertBefore(element, firstChild);
            } else {
                target.appendChild(element);
            }
            return target;
        },
        remove:function (element, child) {
            element.removeChild(child);
            return element;
        },
        empty:function (element) {
            var node;
            while (node = element.firstChild) {
                element.removeChild(node);
            }
            return element;
        },
        destroy:function (element) {
            var parent = this.parent(element);
            if (line.isElement(parent)) {
                return parent.removeChild(element);
            } else {
                return null;
            }
        },
        createElement:(function () {
            var wrap = {
                option:[1, '<select multiple="multiple">', '</select>'],
                optgroup:[1, '<select multiple="multiple">', '</select>'],
                legend:[1, '<fieldset>', '</fieldset>'],
                thead:[1, '<table>', '</table>'],
                tbody:[1, '<table>', '</table>'],
                tfoot:[1, '<table>', '</table>'],
                tr:[2, '<table><tbody>', '</tbody></table>'],
                td:[3, '<table><tbody><tr>', '</tr></tbody></table>'],
                th:[3, '<table><tbody><tr>', '</tr></tbody></table>'],
                col:[2, '<table><colgroup>', '</colgroup><tbody></tbody></table>'],
                _default:[0, '', '']
            };
            var temp = document.createElement('div');
            return function (html) {
                var htmlTag = html.match(/<(\w+)/i);
                if (!htmlTag) {
                    return document.createElement(html);
                }
                var wraper = wrap[htmlTag[1]] || wrap._default,
                    dep = wraper[0],
                    node = null;
                temp.innerHTML = wraper[1] + html + wraper[2];
                node = temp;
                while (dep--) {
                    node = node.firstChild;
                }
                return node.firstChild;
            };
        }())
    });
})(line, line.support, document, window);